{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "ee0afe1d-9fd3-4c01-9bb9-7a3236e10f25",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This little code creates tract- or blockgroup-level 2016 and 2020 votes\n"
     ]
    }
   ],
   "source": [
    "print(\"This little code creates tract- or blockgroup-level 2016 and 2020 votes\")\n",
    "import geopandas as gpd\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import math\n",
    "import ast"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "02d3892a-f47c-4fad-95a7-e9af9ab06359",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I have read in the block group IDs and pops, now do the block level votes\n",
      "our block IDs have character length 3 longer than our tract or blockgroup IDs\n",
      "ready now to sum block votes to tracts or blockgroups\n"
     ]
    }
   ],
   "source": [
    "BGfile = gpd.read_file(\"state_map_files/ca_pl2020_t.dbf\")  #note: use blockgroup and tract terminology interchangeably\n",
    "blockgroupGEOID = [str(BGfile[\"GEOID20\"][i]) for i in range(len(BGfile[\"GEOID20\"])) ]\n",
    "nBGs = len(blockgroupGEOID)\n",
    "bgNameLength = len(blockgroupGEOID[0])\n",
    "bgPop = BGfile[\"P0010001\"]\n",
    "print(\"I have read in the block group IDs and pops, now do the block level votes\")\n",
    "blockFile = pd.read_csv(\"state_map_files/ca_2020_block.csv\")\n",
    "blockFullGEOID = blockFile[\"GEOID20\"]\n",
    "nBlocks = len(blockFullGEOID)\n",
    "blockNameLength = len(str(blockFullGEOID[0]))\n",
    "extraLength = blockNameLength - bgNameLength\n",
    "print(\"our block IDs have character length\",extraLength,\"longer than our tract or blockgroup IDs\")\n",
    "blockDem16 = blockFile[\"pre_16_dem_cli\"]\n",
    "blockRep16 = blockFile[\"pre_16_rep_tru\"]\n",
    "blockDem20 = blockFile[\"pre_20_dem_bid\"]\n",
    "blockRep20 = blockFile[\"pre_20_rep_tru\"]\n",
    "blockShortGEOID = [str(blockFullGEOID[b])[:-extraLength] for b in range(nBlocks)]\n",
    "print(\"ready now to sum block votes to tracts or blockgroups\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "ca474dba-39d9-4597-9d1c-afc55a66e7c9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "our block IDs have character length 4 longer than our tract or blockgroup IDs\n",
      "ready now to sum block votes to blockgroups or tracts\n"
     ]
    }
   ],
   "source": [
    "blockFullGEOID = [\"0\"+str(ID) for ID in blockFullGEOID ]  #block ID's read in without leading zero for CA=state06\n",
    "blockNameLength = len(str(blockFullGEOID[0]))\n",
    "extraLength = blockNameLength - bgNameLength\n",
    "print(\"our block IDs have character length\",extraLength,\"longer than our tract or blockgroup IDs\")\n",
    "blockDem16 = blockFile[\"pre_16_dem_cli\"]\n",
    "blockRep16 = blockFile[\"pre_16_rep_tru\"]\n",
    "blockDem20 = blockFile[\"pre_20_dem_bid\"]\n",
    "blockRep20 = blockFile[\"pre_20_rep_tru\"]\n",
    "blockVAP   = blockFile[\"vap\"]\n",
    "blockWhiteVAP = blockFile[\"vap_white\"]\n",
    "blockHispVAP =  blockFile[\"vap_hisp\"]\n",
    "blockBlackVAP = blockFile[\"vap_black\"]\n",
    "blockAianVAP  = blockFile[\"vap_aian\"]\n",
    "blockAsianVAP = blockFile[\"vap_asian\"]\n",
    "blockNhpiVAP  = blockFile[\"vap_nhpi\"]\n",
    "blockOtherVAP = blockFile[\"vap_other\"]\n",
    "blockTwoVAP =   blockFile[\"vap_two\"]\n",
    "blockShortGEOID = [str(blockFullGEOID[b])[:-extraLength] for b in range(nBlocks)]\n",
    "print(\"ready now to sum block votes to blockgroups or tracts\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "34406989-d7c0-4747-9da3-2251306ac090",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "now we sum those 519723 block votes for 2016 Clinton-Trump and 2020 Biden-Trump\n",
      " ... and for vap stats\n",
      "working on block 0\n",
      "working on block 60000\n",
      "working on block 120000\n",
      "working on block 180000\n",
      "block 222562 had nan values for at least one of the four candidates, so we will skip it\n",
      "working on block 240000\n",
      "working on block 300000\n",
      "working on block 360000\n",
      "working on block 420000\n",
      "block 456235 had nan values for at least one of the four candidates, so we will skip it\n",
      "working on block 480000\n",
      "the 2016 and 2020 GOP 2-party vote shares are 0.33876 0.35088\n",
      "compare these to 0.33872 0.35091\n"
     ]
    }
   ],
   "source": [
    "print(\"now we sum those\",nBlocks,\"block votes for 2016 Clinton-Trump and 2020 Biden-Trump\")\n",
    "bgDem16, bgRep16, bgDem20, bgRep20 =[0 for bg in range(nBGs)],[0 for bg in range(nBGs)],[0 for bg in range(nBGs)],[0 for bg in range(nBGs)]\n",
    "print(\" ... and for vap stats\")\n",
    "bgVAP, bgWhiteVAP, bgHispVAP, bgBlackVAP, bgAianVAP = [0.]*nBGs,[0.]*nBGs,[0.]*nBGs,[0.]*nBGs,[0.]*nBGs\n",
    "bgAsianVAP, bgNhpiVAP, bgOtherVAP, bgTwoVAP =      [0.]*nBGs,[0.]*nBGs,[0.]*nBGs,[0.]*nBGs\n",
    "\n",
    "for b in range(nBlocks):\n",
    "    if b%60000 == 0:\n",
    "        print(\"working on block\",b)\n",
    "    bg = blockgroupGEOID.index( str(blockShortGEOID[b]) )\n",
    "    if not (np.isnan(blockDem20[b]) or np.isnan(blockDem20[b]) or np.isnan(blockDem20[b]) or np.isnan(blockDem20[b]) ) :\n",
    "        bgDem16[bg] += blockDem16[b]\n",
    "        bgRep16[bg] += blockRep16[b]\n",
    "        bgDem20[bg] += blockDem20[b]\n",
    "        bgRep20[bg] += blockRep20[b]\n",
    "        bgVAP[bg]   += blockVAP[b]\n",
    "        bgWhiteVAP[bg]   += blockWhiteVAP[b]\n",
    "        bgHispVAP[bg]    += blockHispVAP[b]\n",
    "        bgBlackVAP[bg]   += blockBlackVAP[b]\n",
    "        bgAianVAP[bg]    += blockAianVAP[b]\n",
    "        bgAsianVAP[bg]   += blockAsianVAP[b]\n",
    "        bgNhpiVAP[bg]    += blockNhpiVAP[b]\n",
    "        bgOtherVAP[bg]   += blockOtherVAP[b]\n",
    "        bgTwoVAP[bg]     += blockTwoVAP[b]\n",
    "    else:\n",
    "        print(\"block\",b,\"had nan values for at least one of the four candidates, so we will skip it\")\n",
    "GOPpct2016 = np.sum(bgRep16)/(np.sum(bgRep16) + np.sum(bgDem16))\n",
    "GOPpct2020 = np.sum(bgRep20)/(np.sum(bgRep20) + np.sum(bgDem20))\n",
    "print(\"the 2016 and 2020 GOP 2-party vote shares are\",round(GOPpct2016,5), round(GOPpct2020,5) )\n",
    "print(\"compare these to\",round(4483810/(4483810+8753788),5),round(6006429  /( 6006429 +11110250),5) )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "124eb8ad-66a0-44b9-9528-f2679b59385e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Now write these to a file in same format as VEST VTD-level presidential votes and VAPs\n"
     ]
    }
   ],
   "source": [
    "print(\"Now write these to a file in same format as VEST VTD-level presidential votes and VAPs\")\n",
    "votesDF = pd.DataFrame( {\"GEOID20\":blockgroupGEOID,\"pop\":bgPop, \"vap\":bgVAP, \"vap_hisp\":bgHispVAP,\n",
    "                         \"vap_white\":bgWhiteVAP, \"vap_black\":bgBlackVAP,\"vap_aian\":bgAianVAP,\n",
    "                         \"vap_asian\":bgAsianVAP,\"vap_nhpi\":bgNhpiVAP, \"vap_other\":bgOtherVAP, \"vap_two\":bgTwoVAP,\n",
    "                         \"pre_16_rep_tru\":bgRep16,\"pre_16_dem_cli\":bgDem16,\n",
    "                         \"pre_20_rep_tru\":bgRep20, \"pre_20_dem_bid\":bgDem20 } )\n",
    "\n",
    "outpath = \"./state_map_files/ca_2020_t.csv\"\n",
    "votesDF.to_csv(outpath)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3e9ce1fb-0c0a-4987-b02c-2b4b101f4224",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
